home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Source.bin / StateCheckBox.java < prev    next >
Text File  |  1998-08-21  |  16KB  |  540 lines

  1. package symantec.itools.awt;
  2.  
  3.  
  4. import java.awt.*;
  5. import java.awt.event.*;
  6. import java.beans.PropertyVetoException;
  7. import java.beans.PropertyChangeListener;
  8. import java.beans.VetoableChangeListener;
  9. import java.beans.PropertyChangeEvent;
  10. import symantec.itools.beans.VetoableChangeSupport;
  11. import symantec.itools.beans.PropertyChangeSupport;
  12.  
  13. //    06/01/97    RKM    Updated to support Java 1.1
  14. //                    Made properties bound & constrained
  15. //                    Converted events
  16. //                    Removed internal enabled (it's in component)
  17. //                    Removed enable & disable overrides, no one else calls repaint
  18. //                    Changed invalidates to repaint
  19. //  07/25/97    CAR marked fields transient as needed
  20. //                  innerclasses implement java.io.Serializable
  21. //                  changed visibility of fields "pressed", "released", "state" and "type" from private to package
  22.  
  23. /**
  24.  * A two- or three-state checkbox that doesn't have an associated text label.
  25.  * A two-state checkbox behaves just like the standard checkbox. In three-state
  26.  * mode clicking the checkbox can switch the checkbox to a third state that
  27.  * appears both gray and checked.
  28.  * <p>
  29.  * The third state is often used to indicate that an attribute of the current
  30.  * selection varies across the selected items. For example, a checkbox used to
  31.  * indicate "bold text" might use the third state if the currently selected
  32.  * text included both bold and plain characters.
  33.  * <p>
  34.  * It is also used to indicate a default action or state.
  35.  * <p>
  36.  * @version 1.0, Nov 26, 1996
  37.  *
  38.  * @author  Symantec
  39.  *
  40.  */
  41. public class StateCheckBox
  42.     extends Canvas
  43. {
  44.     //--------------------------------------------------
  45.     // constants
  46.     //--------------------------------------------------
  47.  
  48.     private static final int WIDTH            = 14;
  49.     private static final int HEIGHT           = 14;
  50.     /**
  51.      * A style constant indicating that this is a two-state checkbox.
  52.      */
  53.     public static final int TWO_STATE         = 0;
  54.     /**
  55.      * A style constant indicating that this is a three-state checkbox.
  56.      */
  57.     public static final int THREE_STATE       = 1;
  58.     /**
  59.      * A state constant indicating that the current state is "unchecked".
  60.      */
  61.     public static final int STATE_UNCHECKED   = 0;
  62.     /**
  63.      * A state constant indicating that the current state is "checked".
  64.      */
  65.     public static final int STATE_CHECKED     = 1;
  66.     /**
  67.      * A state constant indicating that the current state is "default".
  68.      * Default is the third state of a three-state checkbox.
  69.      */
  70.     public static final int STATE_DEFAULT     = 2;
  71.  
  72.     //
  73.     // Constructors
  74.     //
  75.  
  76.     /**
  77.      * Constructs a two-state StateCheckBox that is currently unchecked.
  78.      */
  79.     public StateCheckBox()
  80.     {
  81.         this.type   = TWO_STATE;
  82.         this.state  = STATE_UNCHECKED;
  83.  
  84.         width       = WIDTH;
  85.         height      = HEIGHT;
  86.  
  87.         state       = 0;
  88.  
  89.         pressed     = false;
  90.         released    = true;
  91.     }
  92.  
  93.  
  94.     //--------------------------------------------------
  95.     // accessor methods
  96.     //--------------------------------------------------
  97.  
  98.     /**
  99.      * Sets the current style to two-state or three-state.
  100.      * @param newStyle new StateCheckBox state; either TWO_STATE or THREE_STATE
  101.      * @see #getStyle
  102.      * @see #TWO_STATE
  103.      * @see #THREE_STATE
  104.      * @exception PropertyVetoException
  105.      * if the specified property value is unacceptable
  106.      */
  107.     public void setStyle(int newStyle)
  108.         throws PropertyVetoException
  109.     {
  110.         if (type != newStyle)
  111.         {
  112.             Integer oldStyleInt = new Integer(type);
  113.             Integer newStyleInt = new Integer(newStyle);
  114.  
  115.             vetos.fireVetoableChange("Style",oldStyleInt,newStyleInt);
  116.  
  117.             type = newStyle;
  118.  
  119.             changes.firePropertyChange("Style",oldStyleInt,newStyleInt);
  120.  
  121.             repaint();
  122.         }
  123.     }
  124.  
  125.     /**
  126.      * Gets the current style: two-state or three-state.
  127.      * @return the current StateCheckBox style; either TWO_STATE or THREE_STATE
  128.      * @see #setStyle
  129.      * @see #TWO_STATE
  130.      * @see #THREE_STATE
  131.      */
  132.     public int getStyle()
  133.     {
  134.         return type;
  135.     }
  136.  
  137.     /**
  138.      * Sets the current checkbox state to unchecked, checked, or default.
  139.      * @param newState the new state: STATE_UNCHECKED, STATE_CHECKED, or STATE_DEFAULT
  140.      * @see #getState
  141.      * @see #STATE_UNCHECKED
  142.      * @see #STATE_CHECKED
  143.      * @see #STATE_DEFAULT
  144.      * @exception PropertyVetoException
  145.      * if the specified property value is unacceptable
  146.      */
  147.     public void setState(int newState)
  148.         throws PropertyVetoException
  149.     {
  150.         if (state != newState)
  151.         {
  152.             Integer oldStateInt = new Integer(state);
  153.             Integer newStateInt = new Integer(newState);
  154.  
  155.             vetos.fireVetoableChange("State",oldStateInt,newStateInt);
  156.  
  157.             state = newState;
  158.  
  159.             changes.firePropertyChange("State",oldStateInt,newStateInt);
  160.  
  161.             repaint();
  162.         }
  163.     }
  164.  
  165.     /**
  166.      * Gets the current checkbox state: unchecked, checked, or default.
  167.      * @return the current state: STATE_UNCHECKED, STATE_CHECKED, or STATE_DEFAULT
  168.      * @see #getState
  169.      * @see #STATE_UNCHECKED
  170.      * @see #STATE_CHECKED
  171.      * @see #STATE_DEFAULT
  172.      */
  173.     public int getState()
  174.     {
  175.         return state;
  176.     }
  177.  
  178.     //
  179.     // Methods
  180.     //
  181.  
  182.     /**
  183.      * Adds the specified action listener to receive action events
  184.      * from this button.
  185.      * @param l the action listener
  186.      */
  187.     public synchronized void addActionListener(ActionListener l)
  188.     {
  189.         actionListener = AWTEventMulticaster.add(actionListener, l);
  190.     }
  191.  
  192.     /**
  193.      * Removes the specified action listener so it no longer receives
  194.      * action events from this button.
  195.      * @param l the action listener
  196.      */
  197.     public synchronized void removeActionListener(ActionListener l)
  198.     {
  199.         actionListener = AWTEventMulticaster.remove(actionListener, l);
  200.     }
  201.  
  202.     /**
  203.      * Adds a listener for all event changes.
  204.      * @param listener the listener to add.
  205.      * @see #removePropertyChangeListener
  206.      */
  207.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  208.     {
  209.         //super.addPropertyChangeListener(listener);
  210.         changes.addPropertyChangeListener(listener);
  211.     }
  212.  
  213.     /**
  214.      * Removes a listener for all event changes.
  215.      * @param listener the listener to remove.
  216.      * @see #addPropertyChangeListener
  217.      */
  218.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  219.     {
  220.         //super.removePropertyChangeListener(listener);
  221.         changes.removePropertyChangeListener(listener);
  222.     }
  223.  
  224.     /**
  225.      * Adds a vetoable listener for all event changes.
  226.      * @param listener the listener to add.
  227.      * @see #removeVetoableChangeListener
  228.      */
  229.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
  230.     {
  231.          //super.addVetoableChangeListener(listener);
  232.         vetos.addVetoableChangeListener(listener);
  233.     }
  234.  
  235.     /**
  236.      * Removes a vetoable listener for all event changes.
  237.      * @param listener the listener to remove.
  238.      * @see #addVetoableChangeListener
  239.      */
  240.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
  241.     {
  242.         //super.removeVetoableChangeListener(listener);
  243.         vetos.removeVetoableChangeListener(listener);
  244.     }
  245.  
  246.     //
  247.     // Implmentation
  248.     //
  249.  
  250.     class Mouse extends MouseAdapter implements java.io.Serializable
  251.     {
  252.         /**
  253.          * Processes MOUSE_DOWN events.
  254.          * This is a standard Java AWT method which gets called by the AWT
  255.          * method handleEvent() in response to receiving a MOUSE_DOWN
  256.          * event. These events occur when the mouse button is pressed while
  257.          * inside this component.
  258.          *
  259.          * This method notes that the mouse is pressed inside the box and repaints it.
  260.          *
  261.          * @param e the event
  262.          * @param x the component-relative horizontal coordinate of the mouse
  263.          * @param y the component-relative vertical coordinate of the mouse
  264.          *
  265.          * @return always true since the event was handled
  266.          *
  267.          * @see #mouseUp
  268.          * @see java.awt.Component#handleEvent
  269.          */
  270.         public void mousePressed(MouseEvent e)
  271.         {
  272.             pressed  = true;
  273.             released = false;
  274.  
  275.             repaint();
  276.         }
  277.  
  278.         /**
  279.          * Processes MOUSE_UP events.
  280.          * This is a standard Java AWT method which gets called by the AWT
  281.          * method handleEvent() in response to receiving a MOUSE_UP
  282.          * event. These events occur when the mouse button is released while
  283.          * inside this component.
  284.          *
  285.          * If the mouse was pressed inside the box then the component is repainted
  286.          * and an event is posted.
  287.          *
  288.          * @param e the event
  289.          * @param x the component-relative horizontal coordinate of the mouse
  290.          * @param y the component-relative vertical coordinate of the mouse
  291.          *
  292.          * @return always true since the event was handled
  293.          *
  294.          * @see #mouseDown
  295.          * @see java.awt.Component#handleEvent
  296.          */
  297.         public void mouseReleased(MouseEvent e)
  298.         {
  299.             if (pressed)
  300.             {
  301.                 pressed = false;
  302.  
  303.                 state = (state + 1) % (type == TWO_STATE ? 2 : 3);
  304.  
  305.                 repaint();
  306.  
  307.                 sendActionEvent();
  308.             }
  309.  
  310.             released = true;
  311.         }
  312.  
  313.         /**
  314.          * Processes MOUSE_ENTER events.
  315.          * This is a standard Java AWT method which gets called by the AWT
  316.          * method handleEvent() in response to receiving a MOUSE_ENTER
  317.          * event. These events occur when the mouse first moves over this
  318.          * component.
  319.          *
  320.          * @param e the event
  321.          * @param x the component-relative horizontal coordinate of the mouse
  322.          * @param y the component-relative vertical coordinate of the mouse
  323.          *
  324.          * @return always true since the event was handled
  325.          *
  326.          * @see #mouseExit
  327.          * @see java.awt.Component#handleEvent
  328.          */
  329.         public void mouseEntered(MouseEvent e)
  330.         {
  331.             if (!released)
  332.                 mousePressed(e);
  333.         }
  334.  
  335.         /**
  336.          * Processes MOUSE_EXIT events.
  337.          * This is a standard Java AWT method which gets called by the AWT
  338.          * method handleEvent() in response to receiving a MOUSE_EXIT
  339.          * event. These events occur when the mouse first leaves this
  340.          * component.
  341.          *
  342.          * @param e the event
  343.          * @param x the component-relative horizontal coordinate of the mouse
  344.          * @param y the component-relative vertical coordinate of the mouse
  345.          *
  346.          * @return always true since the event was handled
  347.          *
  348.          * @see #mouseEnter
  349.          * @see java.awt.Component#handleEvent
  350.          */
  351.         public void mouseExited(MouseEvent e)
  352.         {
  353.             if (pressed)
  354.             {
  355.                 pressed = false;
  356.                 repaint();
  357.             }
  358.         }
  359.     }
  360.  
  361.     /**
  362.      * Moves and/or resizes this component.
  363.      * This is a standard Java AWT method which gets called to move and/or
  364.      * resize this component. Components that are in containers with layout
  365.      * managers should not call this method, but rely on the layout manager
  366.      * instead.
  367.      *
  368.      * It is overriden here to note the requested width and height.
  369.      *
  370.      * @param x horizontal position in the parent's coordinate space
  371.      * @param y vertical position in the parent's coordinate space
  372.      * @param width the new width
  373.      * @param height the new height
  374.      */
  375.     public void reshape(int x, int y, int width, int height)
  376.     {
  377.         this.width  = WIDTH;
  378.         this.height = HEIGHT;
  379.  
  380.         super.reshape(x, y, width, height);
  381.     }
  382.  
  383.     /**
  384.      * Returns the recommended dimensions to properly display this component.
  385.      * This is a standard Java AWT method which gets called to determine
  386.      * the recommended size of this component.
  387.      *
  388.      * If this component has been reshaped, then the width and height of that
  389.      * request are returned.
  390.      *
  391.      * @see java.awt.Component#minimumSize
  392.      */
  393.     public Dimension preferredSize()
  394.     {
  395.         return new Dimension(width, height);
  396.     }
  397.  
  398.     /**
  399.      * Paints this component using the given graphics context.
  400.      * This is a standard Java AWT method which typically gets called
  401.      * by the AWT to handle painting this component. It paints this component
  402.      * using the given graphics context. The graphics context clipping region
  403.      * is set to the bounding rectangle of this component and its [0,0]
  404.      * coordinate is this component's top-left corner.
  405.      *
  406.      * @param g the graphics context used for painting
  407.      * @see java.awt.Component#repaint
  408.      * @see java.awt.Component#update
  409.      */
  410.     public void paint(Graphics g)
  411.     {
  412.         g.clipRect(0, 0, width, height);
  413.  
  414.         g.setColor(Color.white);
  415.         g.fillRect(0, 0, width, height);
  416.  
  417.         int w = width - 1, h = height - 1;
  418.  
  419.         if (pressed)
  420.         {
  421.             g.setColor(Color.lightGray);
  422.             g.fillRect(2, 2, w - 4, h - 4);
  423.         }
  424.  
  425.         g.setColor(Color.gray);
  426.         g.drawLine(0, h - 1, 0, 0);
  427.         g.drawLine(0, 0, w - 1, 0);
  428.  
  429.         g.setColor(Color.lightGray);
  430.         g.drawLine(1, h - 2, w - 2, h - 2);
  431.         g.drawLine(w - 2, h - 2, w - 2, 1);
  432.  
  433.         g.setColor(Color.black);
  434.         g.drawLine(1, h - 2, 1, 1);
  435.         g.drawLine(1, 1, w - 2, 1);
  436.  
  437.         switch (state)
  438.         {
  439.             case STATE_DEFAULT :
  440.             {
  441.                 g.setColor(Color.lightGray);
  442.                 g.fillRect(2, 2, w - 4, h - 4);
  443.                 g.setColor(Color.black);
  444.                 // fall through
  445.             }
  446.             case STATE_CHECKED :
  447.             {
  448.                 for (int i = 0; i < 3; ++i)
  449.                 {
  450.                     g.drawLine(3, 5 + i, 5, 7 + i);
  451.                     g.drawLine(5, 7 + i, 9, 3 + i);
  452.                 }
  453.                 break;
  454.             }
  455.             default :
  456.             {
  457.                 break;
  458.             }
  459.         }
  460.     }
  461.  
  462.     /**
  463.      * Tells this component that it has been added to a container.
  464.      * This is a standard Java AWT method which gets called by the AWT when
  465.      * this component is added to a container. Typically, it is used to
  466.      * create this component's peer.
  467.      *
  468.      * @see #removeNotify
  469.      */
  470.     public synchronized void addNotify()
  471.     {
  472.         super.addNotify();
  473.  
  474.         //Hook up listeners
  475.         if (mouse == null)
  476.         {
  477.             mouse = new Mouse();
  478.             addMouseListener(mouse);
  479.         }
  480.     }
  481.  
  482.     /**
  483.      * Tells this component that it is being removed from a container.
  484.      * This is a standard Java AWT method which gets called by the AWT when
  485.      * this component is removed from a container. Typically, it is used to
  486.      * destroy the peers of this component and all its subcomponents.
  487.      *
  488.      * @see #addNotify
  489.      */
  490.     public synchronized void removeNotify()
  491.     {
  492.         //Unhook listeners
  493.         if (mouse != null)
  494.         {
  495.             removeMouseListener(mouse);
  496.             mouse = null;
  497.         }
  498.  
  499.         super.removeNotify();
  500.     }
  501.  
  502.     /**
  503.      * Sends an action performed event to any action listeners, as needed.
  504.      */
  505.     protected void sendActionEvent()
  506.     {
  507.         if (actionListener != null)
  508.             actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null));
  509.     }
  510.  
  511.     // Protected members
  512.     /**
  513.      * Handles tracking vetoable change listeners and notifying them of each change
  514.      * to this component's properties.
  515.      */
  516.     protected VetoableChangeSupport vetos = new VetoableChangeSupport(this);
  517.     /**
  518.      * Handles tracking non-vetoable change listeners and notifying them of each change
  519.      * to this component's properties.
  520.      */
  521.     protected PropertyChangeSupport changes = new PropertyChangeSupport(this);
  522.     /**
  523.      * The this component's mouse event listener.
  524.      */
  525.     protected Mouse mouse = null;
  526.     /**
  527.      * The action listener to keep track of listeners for our action event.
  528.      */
  529.     protected ActionListener actionListener = null;
  530.  
  531.     // Private members
  532.     transient boolean pressed;
  533.     transient boolean released;
  534.     private int width;
  535.     private int height;
  536.     int state;
  537.     int type;
  538. }
  539.  
  540.